using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace Core
{
    public class BuffComponent : Entity, IAwake
    {
        private Dictionary<int, IBuff> buffDict = new Dictionary<int, IBuff>();
        private Unit target;

        public int[] GetAllBuff()
        {
            return buffDict.Keys.ToArray();
        }

        void IAwake.Awake()
        {
            target = GetParent<Unit>();
        }

        public void AddBuff(int[] buffIds)
        {
            if (buffIds == null || buffIds.Length == 0)
                return;

            for (int i = 0; i < buffIds.Length; i++)
            {
                AddBuff(buffIds[i]);
            }
        }

        public bool AddBuff(int buffId)
        {
            var config = World.GetComponent<ConfigComponent>()?.GetConfig<BuffConfig>(buffId);
            if (config == null)
                return false;

            if (!config.isValid)
                return false;

            if (!config.isOverlay)
            {
                if(buffDict.TryGetValue(buffId, out var buff))
                {
                    buff.Dispose();
                }
                
                buff = CreateBuff(buffId, target);
                if(!buff.IsDisposed)
                {
                    buffDict[buffId] = buff;
                }
            }
            else
            {
                if(buffDict.TryGetValue(buffId, out var buff))
                {
                    buff.AddOverlay();
                }
                else
                {
                    buffDict[buffId] = CreateBuff(buffId, target);
                }
            }

            if (config.effect > 0)
            {
                World.GetComponent<EffectComponent>().Create(config.id, Vector3.zero,Vector3.one, Vector3.zero, target.transform);
            }

            return true;
        }

        public void RemoveBuff(int buffId)
        {
            if(buffDict.TryGetValue(buffId, out var buff))
            {
                buff.Dispose();
                buffDict.Remove(buffId);
            }
        }

        public void RemoveBuff(int[] buffIds)
        {
            foreach (var buffId in buffIds)
            {
                if(buffDict.TryGetValue(buffId, out var buff))
                {
                    buff.Dispose();
                    buffDict.Remove(buffId);
                }
            }
        }

        public override void Dispose()
        {
            base.Dispose();

            foreach (var buff in buffDict.Values)
            {
                buff.Dispose();
            }
            buffDict.Clear();
        }

        IBuff CreateBuff(int buffId, Unit target)
        {
            var config = World.GetComponent<ConfigComponent>()?.GetConfig<BuffConfig>(buffId);

            if (config == null)
                return default;

            var type = World.GetComponent<CodeTypes>().GetType(typeof(BuffAttribute), config.type);
            if (type == null)
                return default;

            var buffSystem = Activator.CreateInstance(type) as IBuff;
            if (buffSystem == null)
                return default;

            buffSystem.Awake(config, target);

            if(!buffSystem.IsDisposed)
            {
                target.Scene.World.EventSystem.RegisterSystem(buffSystem);
            }

            return buffSystem;
        }

    }
}